home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Tool Chest / Development Tools & Languages / Macintosh Common Lisp Related / User Contributions / zebu v3.3.3 (LALR parser) / zebu-generator.lisp < prev    next >
Encoding:
Text File  |  1994-09-12  |  32.7 KB  |  1,010 lines  |  [TEXT/ttxt]

  1. ; -*- mode:     CL -*- ----------------------------------------------------- ;
  2. ; File:         zebu-generator.lisp
  3. ; Description:  Generate Domain and Print-Functions for the grammar
  4. ; Author:       Joachim H. Laubsch
  5. ; Created:      25-Feb-92
  6. ; Modified:     Thu Jul 28 10:32:44 1994 (Joachim H. Laubsch)
  7. ; Language:     CL
  8. ; Package:      ZEBU
  9. ; Status:       Experimental (Do Not Distribute) 
  10. ; RCS $Header: $
  11. ;
  12. ; (c) Copyright 1992, Hewlett-Packard Company
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14. ; Revisions:
  15. ; RCS $Log: $
  16. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  17. (IN-PACKAGE  "ZEBU")
  18.  
  19. (declaim (special
  20.           *identifier-continue-chars*
  21.           *identifier-start-chars*
  22.           *domain-structs*
  23.           *domain-types*
  24.           *grammar-options*
  25.           *lex-cats*
  26.           ))
  27.  
  28. ;----------------------------------------------------------------------------;
  29. ; generate-domain-file
  30. ;---------------------
  31. ; Generate the DEFSTRUCT calls to define the domain & dump to FILE
  32. ; When using the meta-grammar, printers will be compiled too.
  33.  
  34. ; file is open when generate-domain-file is called.
  35. ; return true if anything was written.
  36.  
  37. ; If DEFSTRUCT is used in the grammar file  -- *domain-structs*  is not
  38. ; () -- the domain does not need to be generated.
  39.  
  40. (defun generate-domain-file (file port &aux domain printers)
  41.   (unless *domain-structs*
  42.     (when (setq domain
  43.         (prepare-domain
  44.          (or (get-grammar-options-key ':DOMAIN)
  45.              ;; set the domain keyword, s.t. at load time
  46.              ;; the domain definition is present
  47.              (let ((d (process-domain-definition)))
  48.                (when d
  49.              (nconc *grammar-options*
  50.                 (list ':DOMAIN d)))
  51.                d))))        ; sets *domain-type-hierarchy*
  52.       (when (string= (grammar-name *compiler-grammar*)
  53.              "zebu-mg")
  54.     (format t "~%Generating Print-functions ..")
  55.     (setq printers (gen-printers)))))
  56.   (format t "~%Writing domain to ~a~%" file)
  57.   ;; Dump out hierarchy
  58.   (let* ((structs (or (reverse *domain-structs*)
  59.               (generate-domain domain printers)))
  60.      (CL-pkg  #-LUCID (find-package "COMMON-LISP")
  61.           #+LUCID (find-package "LUCID-COMMON-LISP"))
  62.      (Lisp-pkgs
  63.       (cons CL-pkg (package-use-list CL-pkg))))
  64.     (dolist (f structs)
  65.       (let ((struct-name (defstruct-name f)))
  66.     (when (member (symbol-package struct-name)
  67.               Lisp-pkgs)
  68.       (warn "~s was chosen as the name of domain type, ~%but the symbol is already defined in the ~s"
  69.         struct-name (symbol-package struct-name)))        
  70.     (pprint f port)
  71.     (terpri port)
  72.     ;; build the kb-hierarchy even if defstructs are used
  73.     (when *domain-structs*
  74.       (format port "(ZB::DEF-KB-DOMAIN-TYPE '~s '~s '~s)~%"
  75.           struct-name
  76.           (defstruct-super f)
  77.           (defstruct-slots f)))
  78.     ))
  79.     structs))
  80.  
  81. (defun defstruct-name (x)
  82.   (let ((n (cadr x)))
  83.     (if (listp n) (car n) n)))
  84.  
  85. (defun defstruct-super (x)
  86.   (let ((n (cadr x)))
  87.     (when (listp n)
  88.       (let ((include (assoc ':include (cdr n))))
  89.     (when include (second include))))))
  90.  
  91. (defun defstruct-slots (x)
  92.   (mapcar #'(lambda (sd) (if (listp sd) (car sd) sd))
  93.       (cddr x)))
  94.  
  95. ;----------------------------------------------------------------------------;
  96. ; generate-domain
  97. ;----------------
  98. ; Given domain D and an alist PRINTERS with pairs (<type> . <print-function>)
  99. ; return a list of DEFSTRUCT calls
  100.  
  101. (defun generate-domain (d printers &aux code)
  102.   (flet ((parse-slots (l)
  103.        (mapcar #'(lambda (s)
  104.                (if (atom s)
  105.                s
  106.              `(,(car s) nil :type (or null ,(cadr s)))))
  107.            l)))
  108.     (flet ((slots (x)
  109.          (do ((xrest x (cddr xrest)))
  110.          ((null xrest) nil)
  111.            (if (eq (car xrest) ':slots)
  112.            (return (parse-slots (cadr xrest))))))
  113.        (make-struct (name include slots constructor?)
  114.          `(defstruct (,name
  115.               (:include ,include)
  116.               ,@(let ((fn (assoc name printers)))
  117.                   (when fn
  118.                 `((:print-function ,(cdr fn)))))
  119.               ,@(unless constructor?
  120.                   (list '(:constructor nil)))
  121.               )
  122.            ,@slots)))
  123.       (labels ((generate-domain-aux (sub super args constructor?)
  124.          (unless (eq sub super)
  125.            (push (make-struct sub super (slots args) constructor?)
  126.              code))
  127.          (do ((xrest args (cddr xrest))) ((null xrest))
  128.            (when (eq (car xrest) ':subtype)
  129.              (let ((newsub (cadr xrest)))
  130.                (if (atom newsub)
  131.                (push (make-struct newsub sub nil t) code)
  132.              (generate-domain-aux
  133.               (car newsub) sub (cdr newsub) t)))))))
  134.     (when d
  135.       (generate-domain-aux (car d) 'kb-domain (rest d) nil)
  136.       (nreverse code))))))
  137.  
  138.  
  139. ;----------------------------------------------------------------------------;
  140. ; process-domain-definition
  141. ;--------------------------
  142. ; Transform the list of DOMAIN-TYPEs into the hierarchical structure
  143. ; with root KB-DOMAIN, and :SUBTYPE, :SLOTS arcs
  144. (defun process-domain-definition (&aux (R (list 'KB-domain)))
  145.   (labels ((find-super (node supertype)
  146.          ;; node is the list form of the domain def
  147.          (if (null node)
  148.          'Nil
  149.            (if (eq (car node) supertype)
  150.            node
  151.          (do ((n (cdr node) (cddr n)))
  152.              ((null n) nil)
  153.            (when (eq (car n) ':subtype)
  154.              (let ((r (find-super (cadr n) supertype)))
  155.                (when r (return r)))))))))
  156.     (when (null *domain-types*)
  157.       (return-from process-domain-definition nil))
  158.     ;; if there is a supertype in *domain-types* that is 
  159.     ;; undefined, define it as a subtype of KB-domain
  160.     (dolist (node *domain-types*)
  161.       (let ((supertype (domain-type--supertype node)))
  162.     (unless (or (eq supertype 'KB-domain)
  163.             (find supertype *domain-types*
  164.               :key #'domain-type--type))
  165.       (push (make-domain-type
  166.          :-supertype 'KB-domain
  167.          :-type supertype)
  168.         *domain-types*))))
  169.     ;; transform the sorted list to the external :DOMAIN notation
  170.     (let ((domain-types (copy-list *domain-types*)))
  171.       (loop (or domain-types (return R))
  172.         (do ((nodes domain-types (cdr nodes)))
  173.         ((null nodes))
  174.           (let* ((node (first nodes))
  175.              (supertype (domain-type--supertype node))
  176.              (type (domain-type--type node))
  177.              (slots (domain-type--slots node))
  178.              (super (find-super R supertype)))
  179.         (when super
  180.           (nconc super `(:subtype
  181.                  (,type
  182.                   ,@(if slots `(:slots ,slots)))))
  183.           (setq domain-types (delete node domain-types)))))))
  184.     ;; (pprint R)
  185.     R))
  186.  
  187. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  188. ;;                        Generate the print-functions
  189. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  190. ;----------------------------------------------------------------------------;
  191. ; Non-terminal-p
  192. ;---------------
  193. (defun Non-terminal-p (constituent)
  194.   (and (symbolp constituent) (not (assoc constituent *lex-cats*))))
  195.  
  196. ;----------------------------------------------------------------------------;
  197. ; 1-constituent-production-p
  198. ;---------------------------
  199. (defun 1-constituent-production-p (syntax)
  200.   (= 1 (count-if #'Non-terminal-p syntax))
  201.   )
  202.  
  203. (defun first-nt-constituent (syntax)
  204.   (find-if #'Non-terminal-p syntax)
  205.   )
  206.  
  207. ;; collect for each type the lhs and production-rhs in the alist
  208. ;; type-prod-AL ( (<type> . %1=( %2=(<lhs> . <production-rhs>) .. )) ..)
  209. ;; type-print-fn-AL ( (<type> . (lambda ..)) ..)
  210. ;; Return type-print-fn-AL
  211.  
  212. (defun gen-printers (&aux type-prod-AL type-print-fn-AL user-def-types
  213.               KB-sequence-print-fn-AL KB-sequence-prods
  214.               (print-fn-argl (mapcar #'intern 
  215.                          '("ITEM" "STREAM" "LEVEL"))))
  216.   (flet ((memo (type val)
  217.        (let ((bdg  (assoc type type-prod-AL)))
  218.          (if (null bdg)
  219.          (push (cons type (list val)) type-prod-AL)
  220.            (push val (cdr bdg))))))       
  221.     (maphash #'(lambda (key val) (declare (ignore val))
  222.                (unless (or (member key '(:TOP KB-DOMAIN KB-SEQUENCE))
  223.                    (member (symbol-name key)
  224.                        *open-categories*
  225.                        :test #'string=)
  226.                    (assoc key *lex-cats*))
  227.              (push key user-def-types)))
  228.          *domain-ht*)
  229.     ;; for each type, gather a set of productions that produce it
  230.     ;; also check that the type and its slots are defined
  231.     (dolist (zb-rule *zb-rules*)
  232.       (let ((lhs (car zb-rule)))
  233.     (dolist (prod (zb-rule--productions (cdr zb-rule)))
  234.       (let ((semantics (production-rhs--semantics prod)))
  235.         (if (null semantics)
  236.         (let ((syntax (production-rhs--syntax prod)))
  237.           (when (1-constituent-production-p syntax)
  238.             (let ((nt (first-nt-constituent syntax)))
  239.               (when (eq (car (infer-type-disj-of-expr nt))
  240.                 'kb-sequence)
  241.             (memo 'kb-sequence (cons lhs nt))))))          
  242.           (when (and semantics (feat-term-p semantics))
  243.         (let* ((type (feat-term--type semantics))
  244.                (type-node (gethash type *domain-HT*))
  245.                (slots (feat-term--slots semantics)))
  246.           ;; warn about inconsistent use of the types    
  247.           (if (null type-node)
  248.               (warn "Type: ~S is not defined in this domain" type)
  249.             (dolist (slot slots)
  250.               (let ((slot-label (label-value-pair--label slot))
  251.                 (slot-value (label-value-pair--value slot)))
  252.             (if (KB-legal-slot-p type slot-label)
  253.                 (let ((slot-type (KB-slot-type
  254.                           type slot-label)))
  255.                   (unless (eq slot-type ':TOP)
  256.                 (unless (every
  257.                      #'(lambda (sub)
  258.                          (is-subtype-of sub slot-type))
  259.                      (infer-type-disj-of-expr slot-value))
  260.                   (warn "~S type restriction of ~S violated by ~S"
  261.                     slot-type slot-label slot-value)
  262.                   ;;(break "~%> ~S" prod)
  263.                   )))
  264.               (warn "Slot: ~S is not defined for ~S"
  265.                 slot-label type)))))
  266.           (memo type (cons lhs prod))
  267.           (for-each-supertype
  268.            #'(lambda (node)
  269.                (setq user-def-types
  270.                  (delete (type-tree-node--label node)
  271.                      user-def-types)))
  272.            type)))))))))
  273.   (when user-def-types
  274.     (warn "Types:~{ ~S~}~% were defined but not used." user-def-types))
  275.  
  276.   ;; generate print-function for nonterminals which produce a kb-sequence
  277.   (when (setf KB-sequence-prods (assoc 'KB-sequence type-prod-AL))
  278.     (setf type-prod-AL (delete KB-sequence-prods type-prod-AL)
  279.       KB-sequence-print-fn-AL
  280.       (gen-KB-sequence-printers (cdr KB-sequence-prods))))
  281.   ;; (break "KB-sequence-print-fn-AL ~%~S:" KB-sequence-print-fn-AL)
  282.   ;; now generate the print-function for each type
  283.   ;; unless one has been predefined (via the << foo >> Syntax)
  284.   (dolist (e type-prod-AL type-print-fn-AL)
  285.     (let* ((type (car e))
  286.        (domain-type (find type *domain-types*
  287.                   :key #'domain-type--type))
  288.        (fun (when domain-type
  289.           (domain-type-print-function domain-type))))
  290.       ;; (break "domain-type: ~s" domain-type)
  291.       (when (and domain-type (not fun))
  292.     (let ((%1   (cdr e))        ; ((<lhs> . <prod-rhs>)..)
  293.           clauses good-bdgs unused-bdgs)
  294.       (dolist (%2 %1)        ; (<lhs> . <prod-rhs>)
  295.         (push (gen-print-case %2) clauses))
  296.       ;; <clause> = (short-lambda-list syntax binding-list)
  297.       (multiple-value-bind (cond-clauses bindings)
  298.           (gen-clauses clauses KB-sequence-print-fn-AL)
  299.         ;; split bindings in good ones and unused ones
  300.         (dolist (b bindings)
  301.           (if (null (cdr b))
  302.           (pushnew b unused-bdgs)
  303.         (pushnew b good-bdgs)))
  304.         (setf fun `(lambda (,@print-fn-argl 
  305.                 ,@(when good-bdgs `(&aux .,good-bdgs)))
  306.               (declare (ignore 
  307.                   ,@unused-bdgs
  308.                   .,(if (not good-bdgs)
  309.                     print-fn-argl
  310.                       (cddr print-fn-argl))))
  311.             ,(if (cdr cond-clauses)
  312.                  (progn
  313.                    ;; last cond-clause has antecedent T
  314.                    (setf (caar (last cond-clauses)) t)
  315.                    `(cond ,@(simplify-cond-clauses cond-clauses)))
  316.                ;; the condition must be true
  317.                (cadar cond-clauses)))))))
  318.       (push (cons type fun) type-print-fn-AL))))
  319.  
  320. ;;------------------------------------------------------------------------;;
  321. ;; gen-KB-sequence-printers
  322. ;;-------------------------
  323. ;; generate in-line format forms for KB-sequence first:
  324. ;; KB-sequence-print-fn-AL: ((Constituent . <form(lhs)>)..); 
  325.  
  326. (defun gen-KB-sequence-printers (prods &aux Alist separator)
  327.   (dolist (prod prods Alist)
  328.     ;; prod = (<lhs> . <prod-rhs>)  |  (<lhs> . <symbol>)
  329.     (let ((lhs (car prod)) (rhs (cdr prod)))
  330.       ;; (format t "~%~%Prod: ~s ::= ~s" lhs (if (symbolp rhs) rhs (production-rhs--syntax rhs)))
  331.       (setq separator (decode-separator (if (symbolp rhs) rhs lhs))
  332.         Alist (add-print-fn
  333.            lhs
  334.            (if separator
  335.                `(let ((*kb-sequence-separator* ,separator))
  336.              (declare (special *kb-sequence-separator*))
  337.              (KB-SEQUENCE-print ,lhs nil nil))
  338.              `(KB-SEQUENCE-print ,lhs nil nil))
  339.            Alist))
  340.       ;; (format t "~%Separator: ~s" separator)
  341.       )))
  342.  
  343. (defun decode-separator (name)
  344.   ;; return NIL for the default separator
  345.   (let* ((s (symbol-name name))
  346.      (s-length (length s))
  347.      (last-char-pos (1- s-length)))
  348.     (when (char= (schar s last-char-pos) #\$)
  349.       (let ((sep-ln-char (schar s (1- last-char-pos))))
  350.     (when (digit-char-p sep-ln-char)
  351.       (let ((sep-length (- (char-int sep-ln-char) (char-int #\0))))
  352.         (subseq s 
  353.             (- s-length sep-length 2)
  354.             (- last-char-pos 1))))))))
  355.  
  356. ; (defun get-KB-sequence-fillers (seq &aux R)
  357. ;   (dolist (slot (feat-term--slots seq))
  358. ;     (let ((val (LABEL-VALUE-PAIR--VALUE slot)))
  359. ;       (setq r (if (typep val 'feat-term)
  360. ;           (nconc (get-KB-sequence-fillers val) R)
  361. ;         (cons val R)))))
  362. ;   R)
  363.  
  364. ;----------------------------------------------------------------------------;
  365. ; add-print-fn
  366. ;-------------
  367. ; add the print-function FN for the non-terminal CONSTITUENT to ALIST
  368. (defun add-print-fn (CONSTITUENT FN ALIST)
  369.   (let ((bdg (assoc CONSTITUENT ALIST)))
  370.     (if (null bdg)
  371.     (acons CONSTITUENT FN ALIST)
  372.       (progn (setf (cdr bdg)
  373.            `(if (null ,CONSTITUENT)
  374.              ""
  375.              ,(if (equal FN "")
  376.               (cdr bdg)
  377.             FN)))
  378.          ALIST))))
  379.  
  380. ;----------------------------------------------------------------------------;
  381. ; clause
  382. ;-------
  383. ; <lambda-list syntax binding-list semantics>
  384. (defstruct (clause)
  385.   ll syntax bl semantics
  386.   )
  387.  
  388. ;----------------------------------------------------------------------------;
  389. ; gen-print-case
  390. ;---------------
  391. ; given: (<lhs> . <prod-rhs>)
  392. ; return: lambda-list of constituents in lhs
  393. ;         syntax of rhs
  394. ;         for each var in the lambda-list a path of accessors
  395.  
  396. (defun gen-print-case (lhs-rhs-pair)
  397.   (let* ((prod (cdr lhs-rhs-pair))
  398.      (syntax (production-rhs--syntax prod))
  399.      (semantics (production-rhs--semantics prod))
  400.      (ll (mapcan #'(lambda (constituent)
  401.              (unless (stringp constituent) (list constituent)))
  402.              syntax))
  403.      (binding-list
  404.       (mapcar
  405.        #'(lambda (var)
  406.            (let ((p (find-path var semantics)))
  407.          (if (null p)
  408.              (progn
  409.                (warn "~:[Lexical Category~; Non-Terminal~] ~S not used in semantics ~% of ~S."
  410.                  (Non-terminal-p var) var (car lhs-rhs-pair))
  411.                (list var)
  412.                )
  413.            (cons var p))))
  414.           ll)))
  415.     (make-clause
  416.      :ll ll :syntax syntax :bl binding-list :semantics semantics)))
  417.  
  418. ;----------------------------------------------------------------------------;
  419. ; gen-clauses
  420. ;------------
  421. ; Given clauses of the form:
  422. ;  <clause> = <short-lambda-list syntax binding-list semantics>
  423. ; where binding-list = ((<non-terminal-symbol> . <path to access from ITEM>) ..)
  424. ; return: (1) ((<test for print-case> <format stmt derived from syntax>) ..)
  425. ;         (2) a lambda-list binding the %u .. variables used to accessors
  426. ;             derived from the paths.
  427. (defconstant *vars-to-use* '("%R" "%S" "%T" "%U" "%V" "%W" "%X" "%Y" "%Z"))
  428.  
  429. (defun gen-clauses (clauses KB-sequence-print-fn-AL
  430.                 &aux (vars-to-use (mapcar #'intern *vars-to-use*))
  431.                 ;; a set of sets with the same print syntax
  432.                 (partitioning (partition-set #'same-print-syntax clauses))
  433.                 alist cond-clauses)
  434.   (labels ((memo-path (path)
  435.          (let ((bdg (assoc path alist :test #'equal)))
  436.            (if bdg
  437.            (cdr bdg)
  438.          (let ((R (pop vars-to-use)))
  439.            (push (cons path R) alist)
  440.            R))))
  441.        (make-format (syntax bdgs)
  442.          (when syntax
  443.            (let ((R `(format ,(intern "STREAM")
  444.               ,(apply #'concatenate 'string
  445.                   (make-format-string-list syntax))
  446.               ,@(mapcan
  447.                  #'(lambda (const) 
  448.                  (unless (stringp const) 
  449.                    (let ((seq-fn-bdg
  450.                       (assoc
  451.                        const
  452.                        KB-sequence-print-fn-AL))
  453.                      (var (let ((bdg (cdr (assoc const bdgs))))
  454.                         (when bdg (memo-path bdg)))))
  455.                      (list
  456.                       (if seq-fn-bdg
  457.                       `(let ((,const ,var))
  458.                         ,(cdr seq-fn-bdg))
  459.                     (or var
  460.                         (warn "Can't unparse ~s~%~s is unbound in semantics"
  461.                           syntax const)))))))
  462.                  syntax))))
  463.          ;; (format t "~%format: ~s ~a -->~% " syntax bdgs) (pprint R) (break "gen-clauses")
  464.          R))))
  465.     (dolist (eq-print-set partitioning)
  466.       (let (ante (proto  (first eq-print-set)))
  467.     (dolist (eq-print eq-print-set)
  468.       (let ((ll     (clause-ll eq-print))
  469.         (bdgs   (clause-bl eq-print)))
  470.         (pushnew
  471.          (if (null ll)
  472.          (progn 
  473.            ;; (break  "sem: ~s" (clause-semantics eq-print))
  474.            `(equal ,(intern "ITEM") ,(cons-avm
  475.                           (clause-semantics eq-print))))
  476.            (let* (type-list        ; type-preds that have to hold
  477.               (ll-map        ; ((<lvar> . <%var>) ..)
  478.                (mapcar #'(lambda (var)
  479.                    (push (infer-type-predicate var)
  480.                      type-list)
  481.                    (cons var
  482.                      (memo-path
  483.                       (cdr (assoc var bdgs)))))
  484.                    ll))
  485.               (conjuncts
  486.                (mapcan #'(lambda (lvar type)
  487.                    (if (consp type)
  488.                        `((typep ,(cdr lvar) ',type))
  489.                      (if (eq type 'T)
  490.                      ;; delete the variables for which
  491.                      ;; we could not infer a type
  492.                      ()
  493.                        `((,type ,(cdr lvar))))))
  494.                    ll-map (nreverse type-list))))
  495.          (if (cdr conjuncts)
  496.              `(AND . ,conjuncts)
  497.            (car conjuncts))))
  498.          ante :test #'equal)))
  499.     (setq ante (if (cdr ante) (cons 'OR ante) (car ante)))
  500.     (setq cond-clauses
  501.           (insert-clause `(,ante
  502.                    ,(make-format (clause-syntax proto)
  503.                          (clause-bl proto)))
  504.                  cond-clauses))))
  505.     (values cond-clauses
  506.         (mapcar #'(lambda (pair)    ; (<path> .  <%var>)
  507.             (list (cdr pair)
  508.                   (path-to-form (car pair) (intern "ITEM"))))
  509.             alist))))
  510.  
  511. (defun path-to-form (path target)
  512.   (reduce #'(lambda (a b) (list b a))
  513.       path
  514.       :initial-value target))
  515. ;----------------------------------------------------------------------------;
  516. ; insert-clause
  517. ;--------------
  518. ; insert stronger clause at front
  519. (defun insert-clause (clause clauses)
  520.   (flet ((conjunction? (x) (and (consp x) (eq (car x) 'AND)))
  521.      (conjuncts (x) (rest x))
  522.      (typed-var? (x) (and (consp x) (eq (car x) 'TYPEP)))
  523.      (typed-var-nm (x) (cadr x))
  524.      (typed-var-type (x) (cadr (caddr x)))
  525.      (ante (x) (car x)))
  526.     (flet ((weaker-typed? (ante1 ante2)
  527.          (and (typed-var? ante1)
  528.           (typed-var? ante2)
  529.           (eq (typed-var-nm ante1) (typed-var-nm ante2))
  530.           (kb-subtypep (typed-var-type ante2)
  531.                    (typed-var-type ante1)))))
  532.       (if (null clauses)
  533.       (list clause)
  534.         (let ((ante1 (ante clause)))
  535.       ;; (format t "~%a1: ~S~%a2s: ~{~A~%~}" (ante clause) (mapcar #'ante clauses))
  536.       (if (member ante1 clauses :test #'equal :key #'ante)
  537.           ;; the antecedent is already in the clauses
  538.           ;; this indicate a many-to-one surface-to-abstract syntax
  539.           clauses
  540.         (let* ((clause2 (first clauses)) (ante2 (ante clause2)))
  541.           (if (conjunction? ante2)
  542.           (if (conjunction? ante1)
  543.               (if (subsetp ante1 ante2 :test #'weaker-typed?)
  544.               (cons clause2 (insert-clause clause (rest clauses)))
  545.             (cons clause clauses))
  546.             (if (typed-var? ante1)
  547.             (if (find-if #'(lambda (a) (weaker-typed? ante1 a))
  548.                      (conjuncts ante2))
  549.                 (cons clause2 (insert-clause clause (rest clauses)))
  550.               (cons clause clauses))
  551.               (cons clause2 (insert-clause clause (rest clauses)))))
  552.             (if (conjunction? ante1)
  553.             ;; ((and p q) ..) : p  --> ((and p q) p ..) 
  554.             (if (typed-var? ante2)
  555.             (if (find-if #'(lambda (a) (weaker-typed? a ante2))
  556.                      (conjuncts ante1))
  557.                 (cons clause clauses)
  558.               (cons clause2 (insert-clause clause (rest clauses))))
  559.               ;; ante2 is not typed, eg. (IDENTIFIERP %U)
  560.               (if (member ante2 (conjuncts ante1) :test #'equal)
  561.               (cons clause clauses)
  562.             (cons clause2 (insert-clause clause (rest clauses)))))
  563.           ;; both are simple
  564.           (if (weaker-typed? ante1 ante2)
  565.               (cons clause2 (insert-clause clause (rest clauses)))
  566.             (cons clause clauses)))))))))))
  567.  
  568. ;----------------------------------------------------------------------------;
  569. ; same-print-syntax
  570. ;------------------
  571. ; Given clauses rhs A and B
  572. ; where  <clause> = short-lambda-list syntax binding-list
  573. ; return true iff
  574. ; the syntax's constants are the same and its variables have the same bdg
  575. (defun same-print-syntax (a b)
  576.   (let ((a-syntax (clause-syntax a)) (b-syntax (clause-syntax b)))
  577.     (and (equal (length a-syntax) (length b-syntax))
  578.      (every #'(lambda (constituent1 constituent2)
  579.             (or (and (symbolp constituent1) (symbolp constituent2))
  580.             (and (stringp constituent1)
  581.                  (stringp constituent2)
  582.                  (string= constituent1 constituent2))))
  583.         a-syntax b-syntax)            
  584.      ;; syntax is the same
  585.      (let ((a-bdgs (clause-bl a)) (b-bdgs (clause-bl b)))
  586.        ;; do all variables of the lambda-list have the same path?
  587.        (every #'(lambda (u v)
  588.               (equal (cdr (assoc u a-bdgs))
  589.                  (cdr (assoc v b-bdgs))))
  590.           (clause-ll a)
  591.           (clause-ll b))))))
  592.  
  593. ;----------------------------------------------------------------------------;
  594. ; make-format-string-list
  595. ;------------------------
  596. ; This converts a rhs of a grammar rule (SYNTAX) to a format string. 
  597. ; It tries to infer when spaces should be inserted based on the
  598. ; parameter *identifier-continue-chars*
  599. ; As a "rule of style" if a token has a space to its left (right) it should
  600. ; also have one to its right (left), unless the token is the last in syntax.
  601. (defun make-format-string-list (syntax)
  602.   (let ((sep-sq (insert-seperator? syntax))
  603.     (a-tok "~a")
  604.     (s-tok "~s")
  605.     (blank " "))
  606.     ;; const1 const2 ... constn
  607.     ;; sep1   sep1   ... sep1
  608.     ;; enforce the rule of style that a grammar keyword has
  609.     ;; seperators on both sides if it has one on either
  610.     ;; this algorithm is too cuatious, since it does not hurt to
  611.     ;; introduce a seperator!
  612.     (do ((syn-tl syntax (cdr syn-tl))
  613.      (sep-tl sep-sq (cdr sep-tl))
  614.      Acc                ; accumulated result
  615.      )
  616.     ((null syn-tl) (nreverse Acc))
  617.       (let ((const (car syn-tl))
  618.         (sep?  (car sep-tl))
  619.         (preceding-blank? (and Acc
  620.                    (eql (first Acc) blank))))
  621.     (if (stringp const)
  622.         (progn
  623.           (when (and sep? (not preceding-blank?))
  624.         ;; when a seperator follows, then it must precede 
  625.         (push blank Acc))
  626.           (push (escape-tilde const) Acc)
  627.           (when (or sep?
  628.             ;; there is a preceding blank, and not at end
  629.             (and (cdr syn-tl) preceding-blank?))
  630.         (push blank Acc)))
  631.       (let ((firsts (first-terminal (constituent-name const))))
  632.         (if (and (null (rest firsts))
  633.              (string= "STRING" (first firsts)))
  634.         (push s-tok Acc)
  635.           (push a-tok Acc))
  636.         (when sep? (push blank Acc))))))))
  637.  
  638. (defun escape-tilde (string)
  639.   ;; precede each ~ by ~
  640.   (declare (string string))
  641.   (let* ((R "")
  642.      (tilde #\~)
  643.      (p0 0)
  644.      (p1 (position tilde string :test #'eql)))
  645.     (declare (fixnum p0 p1))
  646.     (if p1
  647.     (loop (setq R (concatenate
  648.                'string R (subseq string p0 p1) "~~"))
  649.           (setq p0 (1+ p1))
  650.           (unless (setq p1 (position tilde string
  651.                      :start p0 :test #'eql))
  652.         (return-from escape-tilde
  653.           (concatenate 'string R (subseq string p0)))))
  654.       string)))
  655.  
  656. (defun parse-id/number? (s &aux (n (length s)) state)
  657.   (declare (string s))
  658.   (or                    ; number
  659.    (dotimes (i n t)
  660.      (let ((c (schar s i)))
  661.        (if (null state)
  662.        (if (digit-char-p c)
  663.            nil
  664.          (if (eql c #\.)
  665.          (setq state t)
  666.            (return nil)))
  667.      (if (digit-char-p c)
  668.          nil
  669.        (return nil)))))
  670.                     ; id
  671.    (setq state nil)
  672.    (dotimes (i n t)
  673.      (let ((c (schar s i)))
  674.        (if (null state)
  675.        (if (find c *identifier-start-chars*)
  676.            (setq state t)
  677.          (return nil))
  678.      (if (find c *identifier-continue-chars*)
  679.          nil
  680.        (return nil)))))))
  681.  
  682. (defun insert-seperator? (s)
  683.   ;; -> seq of T/Nil depending on whether the element in s should
  684.   ;; be followed by a seperator
  685.   (declare (list s))
  686.   (flet ((continues-token? (e)
  687.        (declare (string e))
  688.        (or (zerop (length e))
  689.            (let ((c (schar e 0)))
  690.          (declare (character c))
  691.          (if (find c *identifier-continue-chars*)
  692.              t
  693.            (or (digit-char-p c)
  694.                (eql c #\.)))))))
  695.     (maplist #'(lambda (s-tl)
  696.          (let ((e1 (first s-tl)))
  697.            (if (null (rest s-tl))
  698.                ;; e1 is the last element
  699.                ;; by default no seperator after the last const
  700.                nil
  701.              ;; compare e1 to next element, e2
  702.              (let ((e2 (second s-tl)))
  703.                (if (symbolp e1)
  704.                (if (symbolp e2)
  705.                    t
  706.                  ;; the following string e2 could continue
  707.                  ;; the id e1
  708.                  (continues-token? (the string e2)))
  709.              (if (symbolp e2)
  710.                  ;; e1 is a string
  711.                  ;; if it could start an id or number, seperate
  712.                  (parse-id/number? e1)
  713.                ;; e2 is a string
  714.                ;; could it continue a number or an id
  715.                (continues-token? (the string e2))))))))
  716.          s)))
  717.  
  718. ;----------------------------------------------------------------------------;
  719. ; simplify-cond-clauses
  720. ;----------------------
  721. ;  ((and a1 b1) c1)
  722. ;  ((and a1 b2) c2 ..) ..
  723. ; (cond (a1 (cond (b1 c1) (b2 c2))) ..
  724.  
  725. (defun simplify-cond-clauses (clauses)
  726.   (flet ((conj1 (cl) (second cl))
  727.      (conj2 (cl) (third cl))
  728.      (and? (cl) (and (consp cl) (eq (car cl) 'AND))))
  729.     (let* ((cl1 (first clauses))
  730.        (ante1 (car cl1))
  731.        (rest1 (cdr cl1)))
  732.       (if (and (and? ante1) (rest clauses))
  733.       (let* ((cl2 (second clauses))
  734.          (ante2 (car cl2))
  735.          (rest2 (cdr cl2)))
  736.         (if (and (and? ante2) (equal (conj1 ante1) (conj1 ante2)))
  737.         `((,(conj1 ante1) (cond (,(conj2 ante1) .,rest1)
  738.                     (,(conj2 ante2) .,rest2)))
  739.           .,(cddr clauses))
  740.           clauses))
  741.     clauses))))
  742.  
  743. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  744. ;;                      Type Inference for Non-Terminals
  745. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  746.  
  747. (defun type->predicate (type)
  748.   (intern (concatenate 'string (symbol-name type) "-P")
  749.       (symbol-package type)))
  750.  
  751. (defun infer-type-predicate (var &aux (v (constituent-name var)))
  752.   (case v
  753.     (NUMBER     'numberp)
  754.     (IDENTIFIER 'identifierp)
  755.     (STRING     'stringp)
  756.     (t (let ((type (infer-type v)))
  757.      (if (eq type ':TOP)
  758.          (let ((domain-top (car (type-tree-node--subtypes
  759.                      *domain-type-hierarchy*))))
  760.            `(OR
  761.          ,(type-tree-node--label domain-top)
  762.          NUMBER SYMBOL STRING))
  763.        (if (consp type)
  764.            (if (null (rest type))
  765.            (type->predicate (first type))
  766.          (cons 'OR type))
  767.          (if (null type)
  768.          'T
  769.            (type->predicate type))))))))
  770.  
  771.  
  772. (defun infer-type (v)
  773.   (if (member v '(NUMBER IDENTIFIER STRING))
  774.       v
  775.     (let ((disj (infer-type-disj v)))
  776.       (if (null disj)
  777.       (warn "Could not infer type for ~S" v)
  778.     disj))))
  779.  
  780. ;----------------------------------------------------------------------------;
  781. ; is-subtype-of
  782. ;--------------
  783. (defun is-subtype-of (a b)
  784.   (or (eq a b)
  785.       (let ((type-nd (gethash a *domain-HT*)))
  786.     (when type-nd
  787.       (let ((sup (type-tree-node--supertype type-nd)))
  788.         (and sup
  789.          (is-subtype-of (type-tree-node--label sup) b)))))))
  790.  
  791. ;----------------------------------------------------------------------------;
  792. ; kb-subtypep
  793. ;------------
  794. ; disjunctive and conjunctive types are allowed
  795. (defun kb-subtypep (a b)
  796.   (if (consp a)
  797.       (case (first a)
  798.     (OR (every #'(lambda (junct) (kb-subtypep junct b))
  799.            (rest a)))
  800.     (AND (some #'(lambda (junct) (kb-subtypep junct b))
  801.            (rest a)))
  802.     (T nil))
  803.       (if (consp b)
  804.       (case (first b)
  805.         (OR (some #'(lambda (junct) (kb-subtypep junct a))
  806.               (rest b)))
  807.         (AND (every #'(lambda (junct) (kb-subtypep junct a))
  808.             (rest b)))
  809.         (T nil))
  810.     (is-subtype-of a b))))
  811.  
  812. (defun check-domain-type (type node)
  813.   (unless type
  814.     (error "~S is not a defined domain type." node)))
  815.  
  816. (defun infer-type-disj (v &aux (nts (list v)))
  817.   ;; return a list of the possible types for a non-terminal V
  818.   (labels ((infer-type-aux (v disjuncts)
  819.          (if (or (member v '(NUMBER IDENTIFIER STRING))
  820.              (assoc v *lex-cats*))
  821.          (adjoin v disjuncts) 
  822.            (let ((zb-rule (assoc v *zb-rules*))
  823.              (types disjuncts))
  824.          (unless zb-rule
  825.            (error "No Rule/Non-terminal named ~s found" v))
  826.          (dolist (prod (zb-rule--productions (cdr zb-rule)) types)
  827.            (let ((s (production-rhs--semantics prod)))
  828.              (if s
  829.              (if (feat-term-p s)
  830.                  (setq types (adjoin-type-disj
  831.                       (feat-term--type s) types))
  832.                (dolist (type (infer-type s))
  833.                  (setq types (adjoin-type-disj type types))))
  834.                (let ((nt (find-if #'symbolp
  835.                       (production-rhs--syntax prod))))
  836.              (unless (or (null nt) (member nt nts))
  837.                (push nt nts)
  838.                (setq types
  839.                  (infer-type-aux nt types)))))))))))
  840.     (infer-type-aux v nil)))
  841.  
  842. (defun adjoin-type-disj (type disj)
  843.   (if (find type disj :test #'is-subtype-of)
  844.       disj
  845.     (cons type (delete-if #'(lambda (a) (is-subtype-of a type))
  846.               disj))))
  847.                        
  848.   
  849. (defun infer-type-disj-of-expr (x)
  850.   (typecase x
  851.     (number '(number))
  852.     (string '(string))
  853.     (symbol (infer-type-disj (constituent-name x)))))
  854.  
  855. ;----------------------------------------------------------------------------;
  856. ; find-path
  857. ;----------
  858. ; Given a typed feature-structure feat-term, and a variable V occuring
  859. ; somewhere as a value of a slot, return a path to it
  860. ; return: (1) if you are there ()
  861. ;         (2) if there is no path to v: :FAIL
  862. ;         (3) if there is some path: the first one found
  863.  
  864. (defun find-path (v feat-term)
  865.   (labels ((find-path-aux (avl)
  866.          (if (atom avl)
  867.          (if (feat-term-p avl)
  868.              (find-path-list (feat-term--slots avl)
  869.                      (feat-term--type avl))
  870.            (if (eq v avl)
  871.                t
  872.              :FAIL))
  873.            :FAIL))
  874.        (find-path-list (avl type)
  875.          (dolist (lv-pair avl)
  876.            (let ((p (find-path-aux (label-value-pair--value lv-pair))))
  877.          (unless (eq p :FAIL)
  878.            (return
  879.              (cons (intern
  880.                 (concatenate
  881.                  'string
  882.                  (symbol-name type) "-"
  883.                  (symbol-name (label-value-pair--label lv-pair)))
  884.                 (symbol-package type))
  885.                (if (eq p 't) nil p))))))))
  886.     (find-path-aux feat-term)))
  887.  
  888. ;----------------------------------------------------------------------------;
  889. ; partition-set
  890. ;--------------
  891. ; partition SET according to EQUIV-FN
  892. ; for equiv-fn holds (equiv-fn x y) = (equiv-fn y x)
  893.  
  894. (defun partition-set (equiv-fn set &aux alist)
  895.   (do ((x-set set (cdr x-set))) ((null x-set))
  896.     (let ((x (car x-set)))
  897.       (push (list x) alist)
  898.       (do ((y-set (cdr x-set) (cdr y-set))) ((null y-set))
  899.     (let ((y (car y-set)))
  900.       (if (funcall equiv-fn x y)
  901.           (let ((found-association (assoc x alist)))
  902.         (push y (cdr found-association))))))))
  903.   (labels ((partition-set-aux (alist)
  904.          (if (null alist)
  905.          '()
  906.            (let* ((pair1 (car alist))
  907.               (set1 (reduce #'union
  908.                     (mapcar
  909.                      #'(lambda (p)
  910.                      (let ((found (find-if
  911.                                #'(lambda (p1)
  912.                                (member p1 p))
  913.                                pair1)))
  914.                        (when found
  915.                          (setf alist (delete p alist))
  916.                          p)))
  917.                      (cdr alist)) 
  918.                     :initial-value pair1)))
  919.          (cons set1
  920.                (partition-set-aux (cdr alist)))))))
  921.     (partition-set-aux alist)))
  922.  
  923. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  924. ;;                                    tests
  925. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  926.  
  927. #||
  928.  
  929. (GEN-PRINTERS (find-grammar "ex1a"))
  930. (infer-type 'cl-user::ee)
  931. (infer-type 'cl-user::f)
  932. (infer-type 'cl-user::tt)
  933. (infer-type-predicate 'IDENTIFIER)
  934. (infer-type-predicate 'cl-user::ee)
  935.  
  936. (PARTITION-SET #'(lambda (x y)
  937.            (eql (schar (string x) 0)
  938.             (schar (string y) 0)))
  939.            '(a aa aaa b bbb bb c cccc))
  940.  
  941. (PARTITION-SET #'(lambda (x y)
  942.                 (eql (schar (string x) 0)
  943.                  (schar (string y) 0)))
  944.            '(a b c))
  945.  
  946. ;----------------------------------------------------------------------------;
  947. ; partition-set-by-selection-fn
  948. ;------------------------------
  949. ;;; partition set according to selection-fn
  950.  
  951. (defun partition-set-by-selection-fn (selection-fn set &aux alist)
  952.   (dolist (item set)
  953.     (let* ((key (funcall selection-fn item))
  954.        (found-association (assoc key alist :test #'eql)))
  955.       (if found-association 
  956.       (nconc (cdr found-association) (list item))
  957.     (push (cons key (list item)) alist))))
  958.   (dolist (pair alist)
  959.     (setf (car pair) (cadr pair)
  960.       (cdr pair) (cddr pair)))
  961.   alist)
  962.  
  963.  
  964. (partition-set-by-selection-fn #'evenp '(1 2 3 4 5 6 7 8))
  965.  
  966.  ==> ((2 4 6 8) (1 3 5 7))
  967. ||#
  968.  
  969. #||
  970. ;----------------------------------------------------------------------------;
  971. ; follow-terminal
  972. ;----------------
  973. ; given the name of a grammar-symbol, return the
  974. ; list of possibly following strings
  975. (defun follow-terminal (name)
  976.   (mapcar #'g-symbol-name
  977.       (oset-item-list (g-symbol-follow-set (g-symbol-intern name))))
  978.   )
  979. ||#
  980.  
  981. (defun first-terminal (name)
  982.   (mapcan #'(lambda (item)
  983.           (unless (eq item *empty-string-g-symbol*)
  984.         (list (g-symbol-name item))))
  985.       (oset-item-list (g-symbol-first-set (g-symbol-intern name)))))
  986.  
  987. #||
  988. (follow-terminal 'user::ARG)
  989. (first-terminal 'user::ARG*448)
  990. (follow-terminal 'user::ARG*)
  991. (first-terminal 'user::Name)
  992. (first-terminal 'Identifier)
  993.  
  994. (intersection (follow-terminal 'user::ARG) (first-terminal 'user::ARG*438))
  995. (intersection (follow-terminal 'user::stmt) (first-terminal 'user::stmt+))
  996.  
  997. ||#
  998. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  999. ;;                        End of zebu-generator.lisp
  1000. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1001.